using K9Cloud.Identity.Authentication.User;
using K9Cloud.Identity.Data;
using K9Nano.AspNetCore.MultiTenancy;
using K9Nano.Authentication;
using K9Nano.Dependency;
using K9Nano.IdentityServerCore.Data;
using K9Nano.MySql;
using K9Nano.Share;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Logging;
using Microsoft.OpenApi.Models;
using System.Collections.Generic;

namespace K9Cloud.Identity
{
    public class Startup
    {
        private readonly IWebHostEnvironment _env;

        private const string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

        public Startup(IConfiguration configuration, IWebHostEnvironment env)
        {
            Configuration = configuration;
            _env = env;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            /* EFCore */
            var mysqlOption = new MySqlOption();
            Configuration.GetSection("Database").Bind(mysqlOption);

            services.AddMySqlEfCore<K9CloudIdentityDbContext>(mysqlOption, null,
                options =>
                {
                    if (_env.IsDevelopment())
                    {
                        options.EnableSensitiveDataLogging();
                        options.EnableDetailedErrors();
                    }
                });

            /* Dapper */
            services.AddDapper(mysqlOption.SharedScheme);

            /* Identity */
            services.AddK9IdentityCore<K9CloudIdentityDbContext, AppUser, Role, long>();

            /* IdentityServer */
            var migrationsAssembly = typeof(Startup).Assembly.GetName().Name;

            services.AddK9IdentityServer<AppUser, long>(Configuration.GetSection("IdentityServer"),
                config =>
                {
                    Configuration.GetSection("ApiInfo").Bind(config.ApiInfo);

                    config.MultiTenancyConfig.IsEnabled = Configuration.GetSection("MultiTenancy:Enable").Get<bool>();
                    if (config.MultiTenancyConfig.IsEnabled)
                    {
                        services.Configure<MultiTenancyOption>(option => option.DomainFormat = Configuration["MultiTenancy:DomainFormat"]);
                    }
                },
                idsvrOptions =>
                {
                    idsvrOptions.Authority = Configuration["Authentication:Authority"];
                    idsvrOptions.ApiName = K9SharedConstants.IdentityApiName;
                    idsvrOptions.RequireHttpsMetadata = false;
                },
                mvcOptions =>
                {

                })
                .AddConfigurationStore<K9ConfigurationDbContext>(b =>
                {
                    b.ConfigureDbContext = m =>
                        m.UseMySql(mysqlOption, migrationsAssembly);
                })
                .AddOperationalStore<K9PersistedGrantDbContext>(b =>
                {
                    b.ConfigureDbContext = m =>
                        m.UseMySql(mysqlOption, migrationsAssembly);
                })
                .AddDeveloperSigningCredential();

            /* Cache */
            //services.AddK9NanoRedisCache(Configuration.GetSection("Redis"));
            services.AddK9NanoMemoryCache();

            /* DI */
            services.RegisterConventionalAssembly(typeof(Startup).Assembly);

            /* Api Audit */
            services.AddDefaultAudit();
            
            /* Swagger */
            services.AddSwaggerGen(c =>
            {
                c.IgnoreObsoleteActions();
                c.IgnoreObsoleteProperties();
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
            });

            /* CORS */
            services.AddCors(options =>
            {
                options.AddPolicy(MyAllowSpecificOrigins,
                    builder =>
                    {
                        var origins = new List<string>();
                        Configuration.GetSection("Cors:Origins").Bind(origins);

                        builder.WithOrigins(origins.ToArray())
                            .SetIsOriginAllowedToAllowWildcardSubdomains()
                            .AllowAnyHeader()
                            .AllowAnyMethod();
                    });
            });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                SeedData.InitializeDatabase(app);
                IdentityModelEventSource.ShowPII = true;
                app.UseDeveloperExceptionPage();
            }

            app.UseCors(MyAllowSpecificOrigins);

            app.UseK9NanoCore();

            app.UseSwagger();

            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
            });

            app.UseRouting();

            app.UseAuthentication();

            app.UseAuthorization();

            app.UseIdentityServer();

            app.UseDefaultAudit();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}
